001 /*
002 * Copyright 2004 Stephen J. McConnell.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
013 * implied.
014 *
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018
019 package net.dpml.metro.info;
020
021 import java.io.Serializable;
022 import java.util.ArrayList;
023 import java.util.Arrays;
024 import java.util.List;
025
026 /**
027 * A descriptor describing the context that a component
028 * declares. The context descriptor contains information about
029 * context entries accessable via keys (typically mapped to
030 * get[Name] operations on a Context inner interface).
031 *
032 * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
033 * @version 1.0.0
034 */
035 public class ContextDescriptor implements Serializable
036 {
037 //---------------------------------------------------------
038 // static
039 //---------------------------------------------------------
040
041 /**
042 * Serial version identifier.
043 */
044 static final long serialVersionUID = 1L;
045
046 //---------------------------------------------------------
047 // immutable state
048 //---------------------------------------------------------
049
050 private final EntryDescriptor[] m_entries;
051
052 //---------------------------------------------------------
053 // constructors
054 //---------------------------------------------------------
055
056 /**
057 * Creation of a new context descriptor.
058 * @param entries the set of context entries
059 */
060 public ContextDescriptor( final EntryDescriptor[] entries )
061 {
062 if( null == entries )
063 {
064 m_entries = new EntryDescriptor[0];
065 }
066 else
067 {
068 m_entries = entries;
069 }
070 }
071
072 //---------------------------------------------------------
073 // implementation
074 //---------------------------------------------------------
075
076 /**
077 * Return the entries contained in the context.
078 *
079 * @return the array of entries contained in the context.
080 */
081 public EntryDescriptor[] getEntryDescriptors()
082 {
083 return m_entries;
084 }
085
086 /**
087 * Return the entry with specified key.
088 *
089 * @param key the context entry key
090 * @return the entry matching the key of null if no matching entry
091 * @exception NullPointerException if the key argument is null.
092 */
093 public EntryDescriptor getEntryDescriptor( final String key )
094 throws NullPointerException
095 {
096 if ( null == key )
097 {
098 throw new NullPointerException( "key" );
099 }
100
101 for ( int i = 0; i < m_entries.length; i++ )
102 {
103 final EntryDescriptor entry = m_entries[i];
104 if( entry.getKey().equals( key ) )
105 {
106 return entry;
107 }
108 }
109
110 return null;
111 }
112
113 /**
114 * Returns a set of entry descriptors resulting from a merge of the descriptors
115 * contained in this descriptor with the supplied descriptors.
116 *
117 * @param entries the entries to merge
118 * @return the mergerged set of entries
119 * @exception IllegalArgumentException if a entry conflict occurs
120 */
121 public EntryDescriptor[] merge( EntryDescriptor[] entries )
122 throws IllegalArgumentException
123 {
124 for ( int i = 0; i < entries.length; i++ )
125 {
126 EntryDescriptor entry = entries[i];
127 final String key = entry.getKey();
128 EntryDescriptor local = getEntryDescriptor( entry.getKey() );
129 if ( local != null )
130 {
131 if ( !entry.getClassname().equals( local.getClassname() ) )
132 {
133 final String error =
134 "Conflicting entry type for key: " + key;
135 throw new IllegalArgumentException( error );
136 }
137 }
138 }
139
140 return join( entries, getEntryDescriptors() );
141 }
142
143 private EntryDescriptor[] join( EntryDescriptor[] primary, EntryDescriptor[] secondary )
144 {
145 List list = new ArrayList( primary.length + secondary.length );
146 list.addAll( Arrays.asList( primary ) );
147 list.addAll( Arrays.asList( secondary ) );
148 return (EntryDescriptor[]) list.toArray( new EntryDescriptor[0] );
149 }
150
151 /**
152 * Test is the supplied object is equal to this object.
153 * @param other the other object
154 * @return true if the object are equivalent
155 */
156 public boolean equals( Object other )
157 {
158 if( null == other )
159 {
160 return false;
161 }
162 boolean isEqual = true;
163 if( isEqual )
164 {
165 isEqual = other instanceof ContextDescriptor;
166 }
167 if( isEqual )
168 {
169 ContextDescriptor entity = (ContextDescriptor) other;
170 for( int i = 0; i < m_entries.length; i++ )
171 {
172 isEqual = isEqual && m_entries[i].equals( entity.m_entries[i] );
173 }
174 }
175 return isEqual;
176 }
177
178 /**
179 * Return the hashcode for the object.
180 * @return the hashcode value
181 */
182 public int hashCode()
183 {
184 int hash = getClass().hashCode();
185 for( int i = 0; i < m_entries.length; i++ )
186 {
187 hash = hash + 65152197;
188 hash ^= m_entries[i].hashCode();
189 }
190 return hash;
191 }
192 }